package com.ppt.convert.service;

import com.alibaba.fastjson.JSON;
import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.Dispatch;
import com.ppt.convert.domain.Result;
import com.ppt.convert.entity.EduFile;
import com.ppt.convert.entity.FileToImage;
import com.ppt.convert.util.FileUtils;
import com.ppt.convert.util.IdGen;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.*;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author zcx
 * @Title ppt转化逻辑
 * @date 2020年01月19日 16:00
 **/
@Service
public class PptConvertService {

    @Value("${file.preAbsoluteFolder}")
    private String preAbsoluteFolder;

    @Value("${file.afterAbsoluteFolder}")
    private String afterAbsoluteFolder;

    @Autowired
    private UploadService uploadService;

    @Autowired
    private DownLoadService downLoadService;

    private static final Logger logger = LoggerFactory.getLogger(PptConvertService.class);


    /**
     * ppt转图片
     * @author zcx
     * @date 2020-07-01 09:55
     * @param dentryId 文件id
     * @param companyId 机构id
     * @param fileUrl 网盘下载地址
     * @param fileName 文件名
     * @return com.ppt.convert.domain.Result
     */
    public Result pptConvert(String dentryId, String companyId, String fileUrl, String fileName) {
        //要转换的源文件地址
        String fromPath = afterAbsoluteFolder + "download_cqt" + File.separator + dentryId + File.separator + fileName;
        //要转换的源文件父级目录
        String parrentPath = afterAbsoluteFolder + "download_cqt" + File.separator + dentryId;
        //要转换的路径
        String afterPath = afterAbsoluteFolder + "convert_img" + File.separator + dentryId;
        logger.info("网盘下载开始---------------------------------------");
        Result result = downLoadService.downLoadFile(parrentPath,fileUrl, dentryId, fileName);
        if(result.getResp_code()==1) {
            return Result.failed("从网盘下载文件下来失败了----------------");
        }
        logger.info("网盘下载结束---------------------------------------");
        return pptToImage(parrentPath, fromPath, afterPath, dentryId, companyId);
    }


    /**
     * @param fromPath      源文件路径
     * @param pathAfterPath 转化后图片保存路径
     * @return java.lang.String
     * @Description ppt转图片
     * @author zcx
     * @date 2020/1/19 16:06
     **/
    public Result pptToImage(String parrentPath, String fromPath, String pathAfterPath, String dentryId, String companyId) {
        Map<String, Object> resultMap = new HashMap<>();
        ActiveXComponent active = null;
        Dispatch ppt = null;
        try {
            File file = new File(pathAfterPath);
            if (!file.exists()) {
                file.mkdirs(); //创建目录
            }
            long old = System.currentTimeMillis();
            logger.info("convert start---------------------------------------------");
            active = new ActiveXComponent("PowerPoint.Application");//创建一个PPT对象
            Dispatch ppts = active.getProperty("Presentations").toDispatch();//获取文档属性   
            //调用Documents对象中Open方法打开文档，并返回打开的文档对象Document
            //第4，5，6的参数分别表示：ReadOnly,Untititled指定文件是否有标题，WithWindow指定文件是否可见
            ppt = Dispatch.call(ppts, "Open", fromPath, true, true, false).toDispatch();
            //调用office另存为方法
            Dispatch.call(ppt, "SaveAs", pathAfterPath, 17);
            long now = System.currentTimeMillis();
            logger.info("convert OK! ----------------------------------" + ((now - old) / 1000.0) + "秒");
            resultMap = reNameFiles(pathAfterPath, dentryId, companyId);
            return Result.succeed(resultMap, "转化成功");
        } catch (Exception e) {
            return Result.failed("文件转化失败" + e);
        }finally {
            //不管转化失败还是成功都要删除源文件以及转化后的文件
            FileUtils.deleteDirectory(pathAfterPath);
            FileUtils.deleteDirectory(parrentPath);
        }
    }

    /**
     * 将默认生成的幻灯片1.jpg修改成dentryId_1.jpg
     * @author zcx
     * @date 2020-07-01 09:55
     * @param fileDir 文件路径
     * @param dentryId 文件id
     * @param companyId 机构id
     * @return java.util.Map<java.lang.String,java.lang.Object>
     */
    private Map<String, Object> reNameFiles(String fileDir, String dentryId, String companyId) {
        final Map<String, Object> resultMap = new HashMap<>();
        File file = new File(fileDir);
        if (!file.isDirectory()) {
            resultMap.put("fail", "error");
            return resultMap;
        }
        final String parentDir = fileDir;
        final int length = String.valueOf(file.listFiles().length).length();
        if (length == 0) {
            resultMap.put("fail", "error");
            return resultMap;
        }
        final List<String> imageList = new ArrayList<>();
        final List<EduFile> eduFileList = new ArrayList<>();
        final FileToImage fileToImage = new FileToImage();
        fileToImage.setShareFileId(IdGen.uuid());
        fileToImage.setShareFileName("");
        fileToImage.setClassroomId("");
        fileToImage.setCompanyId(companyId);
        fileToImage.setCreateTime(new Timestamp(System.currentTimeMillis()));
        //文件id
        fileToImage.setShareFileDentryId(dentryId);
        String imageListStr = "";
        file.listFiles(new FileFilter() {
            @Override
            public boolean accept(File file) {
                String fileName = file.getName().replace("幻灯片", "").toLowerCase();
                String name = fileName.substring(fileName.indexOf("."), fileName.length());
                String i = fileName.substring(0, fileName.indexOf("."));
                fileName = dentryId + "_" + i + name;
                File newFile = new File(normalizePath(parentDir + File.separator + fileName));
                if (newFile.exists()) {
                    newFile.delete();
                }
                file.renameTo(newFile);
                String resp = uploadService.upload(FileUtils.fileToMultipartFile(newFile));
                if (resp != "error") {
                    Map<String, Object> respMap = JSON.parseObject(resp, Map.class);
                    String path = respMap.get("fileUrl").toString();
                    EduFile imageFile = new EduFile();
                    //设置图片信息
                    imageFile.setOriginalFilename(fileName);
                    imageFile.setFileName(fileName);
                    imageFile.setExtension("jpg");
                    String[] pathList = path.split("/");
                    String pictureId = pathList[pathList.length - 1];
                    imageFile.setDentryId(pictureId);//文件id
                    imageFile.setFileType(1);//类型为图片
                    imageFile.setPath(path);
                    imageFile.setConvertStatus("1");
                    imageFile.setCreateTime(new Timestamp(System.currentTimeMillis()));
                    imageList.add(pictureId);
                    //入库图片信息
                    eduFileList.add(imageFile);
                }
                return true;
            }
        });
        imageListStr = String.join(",", imageList);
        fileToImage.setImages(imageListStr);
        resultMap.put("imageListStr", imageListStr);
        resultMap.put("eduFileList", eduFileList);
        resultMap.put("fileToImage", fileToImage);
        return resultMap;
    }

    /**
     *      * 将文件路径格式化，去掉其中多余的/和\，去掉可能造成文件信息泄露的../
     *      * @param path
     *      * @return
     *     
     */
    private String normalizePath(String path) {
        path = path.replace('\\', '/');
        path = replaceEx(path, "../", "/");
        path = replaceEx(path, "./", "/");
        if (path.endsWith("..")) {
            path = path.substring(0, path.length() - 2);
        }
        path = path.replaceAll("/+", "/");
        return path;
    }

    /**
     *   * 将一个字符串中的指定片段全部替换，替换过程中不进行正则处理
     *   * 使用String类的replaceAll时要求片段以正则表达式形式给出，有时较为不便，可以采用本方法
     *   *
     *   * @param str
     *   * @param subStr
     *   * @param reStr
     *   * @return
     *  
     */
    public String replaceEx(String str, String subStr, String reStr) {
        if ((str == null) || (str.length() == 0) || (reStr == null)) {
            return str;
        }
        if ((subStr == null) || (subStr.length() == 0) || (subStr.length() > str.length())) {
            return str;
        }
        StringBuilder sb = null;
        int lastIndex = 0;
        while (true) {
            int index = str.indexOf(subStr, lastIndex);
            if (index < 0) {
                break;
            }
            if (sb == null) {
                sb = new StringBuilder();
            }
            sb.append(str.substring(lastIndex, index));
            sb.append(reStr);
            lastIndex = index + subStr.length();
        }
        if (lastIndex == 0) {
            return str;
        }
        sb.append(str.substring(lastIndex));
        return sb.toString();
    }

}
